/*
 * Copyright (C), sensetime 2023
 * Author: dingjinfeng
 * Date: 2023/1/3 09:59
 * Description:
 */
package com.senseauto.autorecordlib.ffmpeg;

import android.os.Environment;
import android.util.Log;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.microshow.rxffmpeg.RxFFmpegInvoke;

public class FFmpegManager {
    private static final String TAG = "FFmpegManager";
    private static FFmpegManager instance;
    private ExecutorService ffmpegExecutor = null;
    private static final String DIR_CACHE_NAME = "CarCacheVideo";

    public static FFmpegManager getInstance() {
        if(instance == null) {
            synchronized (FFmpegManager.class) {
                if(instance == null) {
                    instance = new FFmpegManager();
                }
            }
        }
        return instance;
    }

    private FFmpegManager() {
        ffmpegExecutor = Executors.newSingleThreadExecutor();
        File dir = new File(Environment.getExternalStorageDirectory(), DIR_CACHE_NAME);
        dir.mkdirs();
    }

    /**
     * 合并视频
     * @param inputFile 需要合并的视频列表
     * @param targetFile 合并后文件
     */
    public void concatVideo(List<String> inputFile, String targetFile) {
        ffmpegExecutor.execute(()->{
            // 合并视频
            String mergeVideoFilesPath = generateList(inputFile);

            String mergeCmd = String.format("ffmpeg -y -f concat -safe 0 -i %s -acodec copy -vcodec copy -absf aac_adtstoasc %s", mergeVideoFilesPath, targetFile);
            Log.i(TAG, "merge cmd:" + mergeCmd);
            String[] commands = mergeCmd.split(" ");
            int ret1 = RxFFmpegInvoke.getInstance().runFFmpegCmd(commands);
            Log.i(TAG, "mergeCmd: " + mergeCmd + " ret: " + ret1);
        });
    }

    /**
     * 裁剪视频
     * @param startTime 开始时间点
     * @param endTime 结束时间点
     * @param videoPath 视频路径
     * @param finalPath 裁剪后的视频路径
     */
    public void clipVideo(long startTime, long endTime, String videoPath, String finalPath) {
        ffmpegExecutor.execute(()->{
            // 裁剪视频
            SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
            String start = formatter.format(startTime);
            String end = formatter.format(endTime);
            String ClipCmd = String.format("ffmpeg -ss %s -t %s -i %s -vcodec copy -acodec copy %s", start, end, videoPath, finalPath);
            Log.i(TAG, "ClipCmd: " + ClipCmd);
            String[] commands = ClipCmd.split(" ");
            int ret2 = RxFFmpegInvoke.getInstance().runFFmpegCmd(commands);
            Log.i(TAG, "ClipCmd: " + ClipCmd + " ret: " + ret2);
        });
    }

    private static String generateList(List<String> inputs) {
        File list;
        Writer writer = null;
        try {
            list = File.createTempFile("ffmpeg-list", ".txt");
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(list)));
            for (String input: inputs) {
                writer.write("file '" + input + "'\n");
                Log.i(TAG, "Writing to list file: file '" + input + "'");
            }
        } catch (IOException e) {
            e.printStackTrace();
            return "/";
        } finally {
            try {
                if (writer != null)
                    writer.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        Log.i(TAG, "Wrote list file to " + list.getAbsolutePath());
        return list.getAbsolutePath();
    }
}
